package com.lyq.interaction.controller;

import com.lyq.interaction.constant.ConnectionMap;
import com.lyq.interaction.model.Result;
import com.lyq.interaction.model.User;
import com.lyq.interaction.service.UserService;
import com.lyq.interaction.utils.JWTUtil;
import com.lyq.interaction.utils.MD5Util;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Value("${photoPath}")
    private String photoPath;

    /**
     * 保存修改后的用户信息(头像除外)
     */
    @Transactional
    @RequestMapping("/saveUserInfo")
    public Object saveUserInfo(String userName, String password, HttpSession session) {
        log.info("保存修改后的用户信息(头像除外) userName:{} password:{}", userName, password);
        if (!StringUtils.hasLength(userName)) {
            return Result.fail("用户名不能为空");
        }
        if (!isLegislation(userName)) {
            return Result.fail("用户名只能是是英文字母或数字，且长度在2-16之间");
        }
        String userToken = (String) session.getAttribute("userToken");
        Claims user = JWTUtil.checkToken(userToken);
        int id = (Integer) user.get("userId");
        String name = (String) user.get("userName");
        //如果密码为空则不修改密码
        if (StringUtils.hasLength(password)) {
            //更新密码
            password = MD5Util.puzzle(password);
            userService.setPassword(id, password);
        }
        //判断用户名是否已经存在
        if (null == userService.getUserInfo(userName)) {
            //更新用户名
            userService.setUserName(id, userName);
            //更新请求头中的信息
            Map<String, Object> map = new HashMap<>();
            map.put("userId", id);
            map.put("userName", userName);
            session.setAttribute("userToken", JWTUtil.getToken(map));
        } else {
            if (!name.equals(userName)) {
                return Result.fail("用户名已存在");
            }
        }
        return true;
    }

    /**
     * 设置头像
     */
    @RequestMapping("/savePhoto")
    public Object savePhoto(@RequestPart("file") MultipartFile file, HttpSession session) {
        log.info("设置头像");
        String userToken = (String)session.getAttribute("userToken");
        String photoType = file.getContentType();
        if (!"image/png".equals(photoType) && !"image/jpeg".equals(photoType)) {
            return Result.fail("非法的文件类型，应为：.png/.jpeg");
        }
        if (file.getSize() > 1000*1024) {
            return Result.fail("图片过大");
        }
        //获取用户id
        Claims claims = JWTUtil.checkToken(userToken);
        Integer userId = (Integer) claims.get("userId");

        photoType = "image/png".equals(photoType) ? ".png" : ".jpg";
        //保存图片
        try {
            String path = photoPath+userId+photoType;
            file.transferTo(new File(path));
            //将图片路径改为相对路径存储在数据库中
            path = "photo/"+userId+photoType+"?"+ (new Random()).nextInt();
            userService.addPhoto(userId, path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return true;
    }

    /**
     * 模糊搜索用户
     */
    @RequestMapping("/searchByName")
    public List<User> searchByName(String userName, HttpSession session) {
        log.info("搜索用户 userName: {}", userName);
        if (!StringUtils.hasLength(userName)) {
            return new ArrayList<>();
        }
        String toKen = (String)session.getAttribute("userToken");
        Claims claims = JWTUtil.checkToken(toKen);
        Integer userId = (Integer) claims.get("userId");
        return userService.getUserListByName(userName, userId);
    }

    /**
     * 根据token获取登录用户信息
     * @return
     */
    @RequestMapping("/getUserByToken")
    public Object getUserByToken(HttpSession session) {
        log.info("根据token获取登录用户信息");
        if (session == null) {
            //用户未登录
            Result.notAuthority();
        }
        String userToken = (String)session.getAttribute("userToken");
        Claims claims = null;
        try{
            claims = JWTUtil.checkToken(userToken);
        } catch (Exception e) {
            //用户未登录
            Result.notAuthority();
        }
        User userInfo = new User();
        userInfo.setUserId((Integer) claims.get("userId"));
        userInfo.setUserName((String) claims.get("userName"));
        log.info("当前用户为 userId: {} userName: {}", userInfo.getUserId(), userInfo.getUserName());
        //获取用户头像路径
        userInfo.setPhoto(userService.getPhoto(userInfo.getUserId()));
        //返回用户信息
        return Result.success(userInfo);
    }

    /**
     * 获取登录用户信息
     * @return
     */
    @RequestMapping("/mainUser")
    public Object mainUser(HttpSession session) {
        log.info("获取登录用户信息");

        //获取Token接着获取用户信息
        String toKen = (String)session.getAttribute("userToken");
        Claims claims = JWTUtil.checkToken(toKen);

        User userInfo = new User();
        userInfo.setUserId((Integer) claims.get("userId"));
        userInfo.setUserName((String) claims.get("userName"));
        log.info("当前用户为 userId: {} userName: {}", userInfo.getUserId(), userInfo.getUserName());
        //获取用户头像路径
        userInfo.setPhoto(userService.getPhoto(userInfo.getUserId()));
        //返回用户信息
        return Result.success(userInfo);
    }

    /**
     * 登录接口
     */
    @RequestMapping("/login")
    public Object login(String userName, String password, HttpSession session) {
        log.info("用户登录 -> userName:{}, password:{}", userName, password);
        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return Result.fail("登录名或密码不能为空");
        }
        //将账号转为小写
        userName = userName.toLowerCase();
        //获取数据库中该用户的信息
        User user = userService.getUserInfo(userName);
        if (user == null) {
            log.warn("用户不存在或账号已注销 userName：{}", userName);
            return Result.fail("用户不存在或账号已注销");
        }
        //检查用户是否多开
        if (ConnectionMap.getWSSessionById(user.getUserId()) != null) {
            log.warn("用户重复登录 userId: {}, {}", user.getUserId(), ConnectionMap.getWSSessionById(user.getUserId()));
            return Result.fail("该账号不能重复登录");
        }

        //校验密码并返回结果
        if (MD5Util.verify(password, user.getPassword())) {
            log.info("用户登录成功");
            //设置session
            Map<String, Object> map = new HashMap<>();
            map.put("userId", user.getUserId());
            map.put("userName", user.getUserName());
            session.setAttribute("userToken", JWTUtil.getToken(map));
            return Result.success("成功登录");
        }
        else {
            log.info("密码错误");
            return Result.success(null);
        }
    }

    /**
     * 用户注册
     */
    @RequestMapping("/register")
    public Object register(String userName, String password) {
        log.info("用户注册-> userName: {}, password: {}", userName, password);
        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return Result.fail("用户名或密码不能为空");
        }
        //判断用户名是否合法
        if (!isLegislation(userName)) {
            return Result.fail("用户名包含非法字符");
        }
        //将账号转为小写
        userName = userName.toLowerCase();

        if (userService.creatUser(userName, password)) {
            log.info("账号注册成功 userName: {}", userName);
            return true;
        }
        else {
            log.info("账号注册失败 userName: {}", userName);
            return false;
        }
    }

    /**
     * 只允许是英文字母,数字的集合且长度在2-16之间
     * @param userName
     * @return
     */
    public boolean isLegislation(String userName) {
        int len = userName.length();
        log.error(userName);
        if (len < 2 || len > 16) {
            return false;
        }
        for (int i = 0; i < len; i++) {
            char c = userName.charAt(i);
            log.error(c+",");
            if (!((c <= 'z' && c >= 'a') || (c >= 'A' && c <= 'Z') || (c <= 9 && c >= 0))) {
                return false;
            }
        }
        return true;
    }

}
